using System;
using System.IO;

namespace kerberosLibs
{
	/// <summary>
	/// Just like a regular connection task, only it has a process watcher and it routes output
	/// to a common location.
	/// </summary>
	public abstract class LoggingConnectionTask : ConnectionTask
	{
		public LoggingConnectionTask()
		{
		}

		/// <summary>
		/// If true, output process io. If set true when we start, a header will also be written to the
		/// logging.
		/// </summary>
		public bool LogOutput 
		{
			get {return _logging;}
			set {_logging = value;}
		}
		private bool _logging = false;

		/// <summary>
		/// Should we write out the nice header when logging?
		/// </summary>
		public bool WriteLogHeader
		{
			get {return _logHeader;}
			set {_logHeader = value;}
		}
		private bool _logHeader = true;

		/// <summary>
		/// The logging control that all log output should be directed to.
		/// </summary>
		public System.Windows.Forms.TextBoxBase LoggingOutput 
		{
			get {return _loggingControl;}
			set {_loggingControl = value;}
		}
		private System.Windows.Forms.TextBoxBase _loggingControl = null;

		/// <summary>
		/// The running process
		/// </summary>
		protected ProcessWatcher _proc = null;

		/// <summary>
		/// Init the process -- though we don't actually start it.
		/// </summary>
		/// <param name="exe_location"></param>
		/// <param name="exe_args"></param>
		protected void InitProcess (FileInfo exe_location, string exe_args)
		{
			_proc = new ProcessWatcher (exe_location, exe_args);
			_proc.OnProcessOutputLine += new kerberosLibs.ProcessWatcher.ProcessOutputLine(_proc_OnProcessOutputLine);
			_proc.OnProcessExit += new kerberosLibs.ProcessWatcher.ProcessExit(_proc_OnProcessExit);
		}

		/// <summary>
		/// Call to start the process running.
		/// </summary>
		protected void StartProcess ()
		{
			if (_logging && _logHeader) 
			{
				_proc_OnProcessOutputLine ("");
				_proc_OnProcessOutputLine ("------ " + TaskName + ":");
				_proc_OnProcessOutputLine ("");
				_proc_OnProcessOutputLine ("Exe Path: " + _proc.ExeLocation);
				_proc_OnProcessOutputLine ("Arguments: " + _proc.ExeArguments);
				_proc_OnProcessOutputLine ("------ ");
			}
			_proc.Start();
		}

		/// <summary>
		/// Kill off the task -- hard!
		/// </summary>
		public void KillTask ()
		{
			if (_proc != null) 
			{
				_proc.Kill();
			}
		}

		private delegate void LogOutputLineDelegate (string line);

		/// <summary>
		/// Call back when it is time to add text to the output! Save to call from any thread.
		/// </summary>
		/// <param name="line"></param>
		private void _proc_OnProcessOutputLine(string line)
		{
			if (line == null || !_logging || _loggingControl == null) 
			{
				return;
			}

			///
			/// If we are on the wrong thread, fix it!
			/// 

			if (_loggingControl.InvokeRequired) 
			{
				LogOutputLineDelegate l = new LogOutputLineDelegate (this._proc_OnProcessOutputLine);
				_loggingControl.BeginInvoke (l, new object[1] {line});
				return;
			}

			///
			/// Ok -- out of the woods. Now log it!
			///

			_loggingControl.AppendText (line);
			_loggingControl.AppendText (System.Environment.NewLine);
		}

		public delegate void ProcessExitDelegate ();

		/// <summary>
		/// Raised when a process has exited!
		/// </summary>
		public event ProcessExitDelegate ProcessExited;

		/// <summary>
		/// Our child died. Let everyone who cares know!
		/// </summary>
		private void _proc_OnProcessExit()
		{
			if (ProcessExited != null) 
			{
				ProcessExited ();
			}
		}
	}
}
